﻿#include<iostream>

using namespace std;


//int main()
//{
//	int a = 0;
//	// 引用：b和c是a的别名
//	//类型& 引用别名 = 引用对象
//	int& b = a;
//	int& c = a;
//
//	// 也可以给别名b取别名，d相当于还是a的别名
//	int& d = b;
//	++d;
//	// 这⾥取地址我们看到是⼀样的
//	cout << &a << endl;
//	cout << &b << endl;
//	cout << &c << endl;
//	cout << &d << endl;
//	return 0;
//
//	return 0;
//}
//


//int main()
//{
//	int a = 0;
//	// 编译报错：“ra”: 必须初始化引用
//	//int& ra;
//	int& b = a;
//	
//	cout << &a << endl;
//	cout << &b << endl;
//	
//	return 0;
//}

//int main()
//{
//	int a = 0;
//	int& b = a;
//
//	int c = 20;
//	// 这里并非让b引用c，因为C++引用不能改变指向，
//	//b是一个引用变量，b已经引用了a这个实体，不能再引用c那个实体
//	// 这里是⼀个赋值
//	b = c;
//	cout << &a << endl;
//	cout << &b << endl;
//	cout << &c << endl;
//	return 0;
//}


//void Swap(int& rx, int& ry)
//{
//	int tmp = rx;
//	rx = ry;
//	ry = tmp;
//}
//int main()
//{
//	int x = 0, y = 1;
//	cout << x << " " << y << endl;
//	Swap(x, y);
//	cout << x << " " << y << endl;
//	return 0;
//}



//#include<iostream>
//#include<assert.h>
//
//using namespace std;
//typedef int STDataType;
//typedef struct Stack
//{
//	STDataType* a;
//	int top;
//	int capacity;
//}ST;
//
//
////ST& rs 引用传参，改变引用对象的同时，改变被引用对象
//void STInit(ST& rs, int n = 4)
//{
//	rs.a = (STDataType*)malloc(n * sizeof(STDataType));
//	rs.top = 0;
//	rs.capacity = n;
//}
//
//// 栈顶
//void STPush(ST& rs, STDataType x)
//{
//	// 满了， 扩容
//	if (rs.top == rs.capacity)
//	{
//		printf("扩容\n");
//		int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;
//		STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity *sizeof(STDataType));
//		if (tmp == NULL)
//		{
//			perror("realloc fail");
//			return;
//		}
//		rs.a = tmp;
//		rs.capacity = newcapacity;
//	}
//	rs.a[rs.top] = x;
//	rs.top++;
//}
//
//void STModityTop(ST& rs, int x)
//{
//	rs.a[rs.top-1] = x;
//}
//
//// int STTop(ST& rs)
//int& STTop(ST& rs)
//{
//	assert(rs.top > 0);
//	return rs.a[rs.top-1];
//}
//
//int& func()
//{
//	int a = 0;
//	return a;
//}
//
//int main()
//{
//	// 调用全局的
//	ST st1;
//	STInit(st1);
//	STPush(st1, 1);
//	STPush(st1, 2);
//
//	//修改栈顶元素
//	STModityTop(st1, 3);
//	//在int& STTop(ST& rs)的条件下，下面这种写法是正确的
//	//直接修改栈顶元素
//	STTop(st1) = 4;
//
//	//但如果是int STTop(ST& rs)，就不能直接更改
//
//	return 0;
//}


//#include<iostream>
//
//using namespace std;
//
//typedef struct SeqList
//{
//	int a[10];
//	int size;
//}SLT;
//
//typedef struct ListNode
//{
//	int val;
//	struct ListNode* next;
//}LTNode, * PNode;
//
//// 指针变量也可以取别名，这里LTNode*& phead就是给指针变量取别名
//// 这样就不需要用二级指针了，相对而言简化了程序
////void ListPushBack(LTNode** phead, int x)
////void ListPushBack(LTNode*& phead, int x)
//void ListPushBack(PNode& phead, int x)
//{
//	PNode newnode = (PNode)malloc(sizeof(LTNode));
//	newnode->val = x;
//	newnode->next = NULL;
//	if (phead == NULL)
//	{
//		phead = newnode;
//	}
//	else
//	{
//		//...
//	}
//}
//
//
//int main()
//{
//	PNode plist = NULL;
//	ListPushBack(plist, 1);
//	return 0;
//}
//


//int main()
//{
//	const int a = 10;//只能读，不能写
//
//	// 编译报错：error C2440: “初始化”: 无法从“const int”转换为“int &”
//	// 这里的引用是对a访问权限的放大
//	//int& ra = a;
//	// 这样才可以
//
//	const int& ra = a;//权限平移
//
//	// 编译报错：error C3892: “ra”: 不能给常量赋值
//	//ra++;只能读，不能改
//	
//
//	// 这里的引用是对b访问权限的缩小
//	int b = 20;//可读可写
//
//	const int& rb = b;//只读不写
//
//	// 编译报错：error C3892: “rb”: 不能给常量赋值
//	//rb++;
//
//	return 0;
//}


//void func(const int& val)//结果保存在一个临时对象中，临时对象具有常性，必须用常引用
//{
//
//}
//
//int main()
//{
//	const int a = 10;
//	//int rd = a;
//	//int& ra = a;
//
//	const int& ra = a;
//
//	// 引用的时候权限可以缩小，但是不能放大
//	int b = 20;
//	const int& rb = b;
//	b++;
//	//rb++;
//
//	const int& rc = 30;//常量
//	const int& rd = (a + b);//表达式，结果保存在一个临时对象中，临时对象具有常性，必须用常引用
//
//	double d = 12.34;
//	int i = d;//类型提升，结果保存在一个临时对象中，临时对象具有常性，必须用常引用
//
//	const int& ri = d;
//	//double& rd = d;
//
//	func(a);//传值传参
//	func(b);
//	func(30);
//	func(a+b);
//	func(d);
//
//	return 0;
//}


// //实现一个ADD宏函数的常见问题
////#define ADD(int a, int b) return a + b;
////#define ADD(a, b) a + b;
////#define ADD(a, b) (a + b)
//
//// 正确的宏实现
//#define ADD(a, b) ((a) + (b))
//// 为什么不能加分号?
//// 有些情况下，加分号可能不会报错，那如果在一些语句中多了一个分号是不可以，比如if语句
//
//// 为什么要加外面的括号?
//// 为什么要加里面的括号?
////在这两个位置加括号是为了避免因优先级的问题导致结果出现偏差
//
//int main()
//{
//	int ret = ADD(1, 2); // int ret = ((1)+(2));
//	cout << ADD(1, 2) << endl;
//
//	cout << ADD(1, 2) * 5 << endl;
//
//	int x = 1, y = 2;
//	ADD(x & y, x | y); // -> (x&y+x|y)
//
//	return 0;
//}


//inline int Add(int x, int y)
//{
//	int ret = x + y;
//
//	return ret;
//}
//
//int main()
//{
//	int ret = Add(1, 2); 
//
//	cout << Add(1, 2) * 5 << endl;
//	cout << ret << endl;
//
//	return 0;
//}

// F.h
//#include <iostream>
//
//using namespace std;
//
//inline void f(int i);
// F.cpp
//#include "F.h"
//void f(int i)
//{
//	cout << i << endl;
//}
// main.cpp
//#include "F.h"
//int main()
//{
//	 链接错误：无法解析的外部符号 "void __cdecl f(int)" (?f@@YAXH@Z)
//	f(10);
//	return 0;
//}

#include<iostream>

using namespace std;

void f(int x)
{
	cout << "f(int x)" << endl;
}
void f(int* ptr)
{
	cout << "f(int* ptr)" << endl;
}
int main()
{
	f(0);
	// 本想通过f(NULL)调用指针版本的f(int*)函数，但是由于NULL被定义成0，
	// 调用了f(intx)，因此与程序的初衷相悖。
	f(NULL);
	f((int*)NULL);
	
    // 编译报错：error C2665: “f”: 2 个重载中没有⼀个可以转换所有参数类型
	// f((void*)NULL);
	//在C语言中void* 能转化为任意类型的指针，但是在C++中是不允许的，
		
	f(nullptr);
	
	 return 0;
	
}




